package com.inspur.cloud.security;

import com.inspur.cloud.configuration.ApiConfig;
import com.inspur.cloud.util.AESUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ApiAutoLoginFilter extends BasicAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    private AuthenticationEntryPoint authenticationEntryPoint;

    private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();

    @Autowired
    private ApiConfig apiConfig;

    public ApiAutoLoginFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
        super(authenticationManager);
        this.authenticationManager = authenticationManager;
        this.authenticationEntryPoint = authenticationEntryPoint;
    }

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (!shouldApply(request)) {
            chain.doFilter(request, response);
            return;
        }
        try {
            String username = request.getParameter("account");
            String pass = request.getParameter("passwd");
            String password = AESUtil.decrypt(pass, 0);
            String validator = request.getParameter("validator");
            String timeStr = AESUtil.decrypt(validator, 0);
            Long time = Long.valueOf(timeStr);
            Long now = System.currentTimeMillis();
            if (now - time > 1000 * 60 * 30 || now - time < -1000 * 60 * 30) {
                chain.doFilter(request, response);
                return;
            }
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
            authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
            Authentication authentication = authenticationManager.authenticate(authRequest);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            this.onSuccessfulAuthentication(request, response, authentication);
            chain.doFilter(request, response);
        } catch (AuthenticationException e) {
            SecurityContextHolder.clearContext();
            this.onUnsuccessfulAuthentication(request, response, e);
            authenticationEntryPoint.commence(request, response, e);
            return;
        }
    }

    private boolean shouldApply(HttpServletRequest request) {
        String method = request.getMethod();
        if (StringUtils.isEmpty(method) || !"POST".equals(method)) {
            return false;
        }
        String validator = request.getParameter("validator");
        if (StringUtils.isEmpty(validator)) {
            return false;
        }
        return true;
    }
}
